﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Migrator.Util;

namespace Migrator.Services.RouteOptimization
{
    /// <summary>
    /// Mobility binding cache, used by nodes supporting
    /// route optimization
    /// </summary>
    public class BindingCache
    {
        /// <summary>
        /// Adds a new entry to the mobility binding cache
        /// </summary>
        /// <param name="entry">The entry to add</param>
        public void Add(Entry entry)
        {
            table[entry.HomeAddress] = entry;
        }

        public bool Contains(IPAddress homeAddress)
        {
            return this.table.ContainsKey(homeAddress);
        }

        /// <summary>
        /// Removes the entry for the given home address.
        /// </summary>
        /// <param name="homeAddress"The home address to deregister></param>
        public void Remove(IPAddress homeAddress)
        {
            this.table.Remove(homeAddress);   
        }

        /// <summary>
        /// Removes expired entries
        /// </summary>
        /// <param name="now">The current clock time</param>
        /// <returns>The list of entries deleted</returns>
        public List<Entry> RemoveExpired(int now)
        {
            var toRemove = this.table.Values.Where(entry => entry.ExpirationTime < now).ToList();
            
            foreach (var entry in toRemove)
            {
                this.table.Remove(entry.HomeAddress);
            }

            return toRemove;
        }

        public Entry this[IPAddress homeAddress]
        {
            get { return table[homeAddress]; }
        }

        /// <summary>
        /// Mobility binding cache
        /// </summary>
        private Dictionary<IPAddress, Entry> table = new Dictionary<IPAddress, Entry>();

        /// <summary>
        /// Mobility binding cache entry
        /// </summary>
        public class Entry
        {
            public Entry(IPAddress homeAddress, IPAddress careOfAddress, int expirationTime)
            {
                this.HomeAddress = homeAddress;
                this.CareOfAddress = careOfAddress;
                this.ExpirationTime = expirationTime;
            }

            public IPAddress HomeAddress
            {
                get;
                private set;
            }

            public IPAddress CareOfAddress
            {
                get;
                private set;
            }

            public int ExpirationTime
            {
                get;
                private set;
            }
        }
    }
}
